/*
 * Android Runner is a multiplayer GPS game fully written by Xurxo Mendez Perez
 * 
 * Copyright (C) 2009 Xurxo Mendez Perez
 *   
 * This file is part of Android Runner.
 * 
 * Android Runner is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Android Runner is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Android Runner.  If not, see <http://www.gnu.org/licenses/>.
 */

package es.sonxurxo.androidrunner.model.persistence.player.entity;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;

import org.hibernate.annotations.AccessType;

import es.sonxurxo.androidrunner.model.persistence.game.entity.FinishedGameRegister;
import es.sonxurxo.androidrunner.model.persistence.game.entity.Game;
import es.sonxurxo.androidrunner.model.persistence.item.entity.Item;

/**
 * 
 * @author "Xurxo Mendez Perez"
 *
 */
@Entity
public class Player {
	
	private long playerId;
	private UserData userData;
	private int points;
	private int totalPoints;
	private int maxPoints;
	private int bestRank;
	private int imageId;
	private Game game = null;
	private int latitude;
	private int longitude;
	private boolean messageChanges = false;
	private boolean itemChanges = false;
	private Set<Item> itemsICanSee = new HashSet<Item>();
	private Set<Item> itemsIHave = new HashSet<Item>();
	private Set<FinishedGameRegister> finishedGameRegisters = 
		new HashSet<FinishedGameRegister>();
	
	public Player() {
		// Empty on purpose
	}
	
	public Player(String login, String password, String email, boolean showPersonalInfo, 
			String phone, String name, String surname, String country, int imageId, String role) {
		super();
		this.userData = new UserData(login, password, email, showPersonalInfo, phone, name, 
				surname, country, role);
		this.points = 0;
		this.totalPoints = 0;
		this.latitude = 42341185;
		this.longitude = -7863749;
		this.imageId = imageId;
	}

	public boolean isMessageChanges() {
		return this.messageChanges;
	}

	public void setMessageChanges(boolean messageChanges) {
		this.messageChanges = messageChanges;
	}

	public boolean isItemChanges() {
		return this.itemChanges;
	}

	public void setItemChanges(boolean itemChanges) {
		this.itemChanges = itemChanges;
	}

	public int getImageId() {
		return this.imageId;
	}

	public void setImageId(int imageId) {
		this.imageId = imageId;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "gameId")
	public Game getGame() {
		return this.game;
	}

	public void setGame(Game game) {
		this.game = game;
	}

	@OneToMany(mappedBy = "player", fetch = FetchType.LAZY)
	public Set<FinishedGameRegister> getFinishedGameRegisters() {
		return this.finishedGameRegisters;
	}

	public void setFinishedGameRegisters(
			Set<FinishedGameRegister> finishedGameRegisters) {
		this.finishedGameRegisters = finishedGameRegisters;
	}
	
	public void addFinishedGameRegister(FinishedGameRegister finishedGameRegister) {
		this.finishedGameRegisters.add(finishedGameRegister);
		finishedGameRegister.setPlayer(this);
	}

	public void removeFinishedGameRegister(FinishedGameRegister finishedGameRegister) {
		this.finishedGameRegisters.remove(finishedGameRegister);
		finishedGameRegister.setPlayer(null);
	}
	
	@ManyToMany(
			fetch = FetchType.LAZY,
			targetEntity = Item.class, // no es necesario
			cascade = {CascadeType.PERSIST, CascadeType.MERGE})
	@JoinTable(
			name = "PlayerSeeItem",
			joinColumns = @JoinColumn(name = "playerId"),
			inverseJoinColumns = @JoinColumn(name = "itemId"))
	@AccessType("field")
	public Set<Item> getItemsICanSee() {
		return this.itemsICanSee;
	}

	public void setItemsICanSee(Set<Item> itemsICanSee) {
		this.itemsICanSee = itemsICanSee;
	}
	
	public void addItemICanSee(Item item) {
		this.itemsICanSee.add(item);
		item.getPlayersCanSeeMe().add(this);
	}
	
	public void removeItemICanSee(Item item) {
		this.itemsICanSee.remove(item);
		item.getPlayersCanSeeMe().remove(this);
	}
	
	@ManyToMany(
			fetch = FetchType.LAZY,
			targetEntity = Item.class, 
			cascade = {CascadeType.PERSIST, CascadeType.MERGE})
	@JoinTable(
			name = "PlayerHasItem",
			joinColumns = @JoinColumn(name = "playerId"),
			inverseJoinColumns = @JoinColumn(name = "itemId"))
	public Set<Item> getItemsIHave() {
		return this.itemsIHave;
	}

	public void setItemsIHave(Set<Item> itemsIHave) {
		this.itemsIHave = itemsIHave;
	}

	public void addItemIHave(Item item) {
		this.itemsIHave.add(item);
		item.getPlayersHaveMe().add(this);
	}
	
	public void removeItemIHave(Item item) {
		this.itemsIHave.remove(item);
		item.getPlayersHaveMe().remove(this);
	}
	
	public int getLatitude() {
		return this.latitude;
	}

	public void setLatitude(int latitude) {
		this.latitude = latitude;
	}

	public int getLongitude() {
		return this.longitude;
	}

	public void setLongitude(int longitude) {
		this.longitude = longitude;
	}

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO,
            generator="PlayerIdGenerator")
    @SequenceGenerator(             // It only takes effect for
            name="PlayerIdGenerator", // databases providing identifier
            sequenceName="PlayerSeq") // generators.
	public long getPlayerId() {
		return this.playerId;
	}

	public void setPlayerId(long playerId) {
		this.playerId = playerId;
	}

	public int getPoints() {
		return this.points;
	}

	public void setPoints(int points) {
		this.points = points;
	}

	public int getTotalPoints() {
		return this.totalPoints;
	}

	public void setTotalPoints(int totalPoints) {
		this.totalPoints = totalPoints;
	}
	
	public int getBestRank() {
		return this.bestRank;
	}

	public void setBestRank(int bestRank) {
		this.bestRank = bestRank;
	}

	public int getMaxPoints() {
		return this.maxPoints;
	}

	public void setMaxPoints(int maxPoints) {
		this.maxPoints = maxPoints;
	}
	
	public boolean equals(Player player) {
		return this.playerId == player.getPlayerId();
	}

	@Embedded
	public UserData getUserData() {
		return this.userData;
	}

	public void setUserData(UserData userData) {
		this.userData = userData;
	}	
}
